#include <cassert>
#include <cstdint>
#include <cstdio>
#include <functional>
#include <stack>
#include <string>
#include <map>
#include <vector>

class StyledTexts {
public:
    struct Style {
        uint32_t color;
        const char *families;

        bool operator ==(const Style &rhs) const
        {
            return color == rhs.color && families == rhs.families;
        }
    };

    void PushStyle(const struct Style &style)
    {
        for (int i = 0; i < styleTable.size(); i++) {
            if (style == styleTable[i]) {
                styleKeyStack.push(i);
                return;
            }
        }

        styleKeyStack.push(styleTable.size());
        styleTable.push_back(style);
    }

    void PopStyle()
    {
        styleKeyStack.pop();
    }

    void AddText(const std::string &text)
    {
        assert(text.size() > 0);
        textTable.push_back({.text = text, .styleKey = styleKeyStack.top()});
    }

private:
    struct TextTable {
        std::string text;
        int styleKey;
    };
    std::stack<int> styleKeyStack;
    std::vector<TextTable> textTable;
    std::vector<struct Style> styleTable;

public:
    struct IterResult {
        std::string *text;
        struct Style *style;
    };

    class Iter {
        std::vector<TextTable>::iterator it;
        StyledTexts &texts_;
        struct IterResult now;
    public:
        Iter(StyledTexts &texts, std::vector<TextTable>::iterator itor)
            : it(itor), texts_(texts)
        {
            now = {&it->text, &texts_.styleTable[it->styleKey]};
        }

        bool operator !=(const Iter &rhs)
        {
            return it != rhs.it;
        }

        void operator++()
        {
            it++;
            now = {&it->text, &texts_.styleTable[it->styleKey]};
        }

        struct IterResult& operator*()
        {
            return now;
        }
    };

    Iter begin() { return {*this, textTable.begin()}; }
    Iter end() { return {*this, textTable.end()}; }
};

int main()
{
    std::vector<void(*)()> v1;
    v1.push_back([](){printf("1\n");});
    v1.push_back([](){printf("2\n");});
    v1.push_back([](){printf("3\n");});

    std::vector<std::function<void()>> v2;
    v2.push_back([](){printf("1\n");});
    v2.push_back([](){printf("2\n");});
    v2.push_back([](){printf("3\n");});

    std::map<int, std::function<void()>> m;
    m[0] = ([](){printf("1\n");});
    m[1] = ([](){printf("2\n");});
    m[2] = ([](){printf("3\n");});

    for (const auto &v : v2) {
        v();
    }

    for (auto it = v2.begin(); it != v2.end(); it++) {
        (*it)();
    }

    for (const auto &iter : m) {
        printf("%d: ", iter.first);
        iter.second();
    }

    for (auto it = m.begin(); it != m.end(); it++) {
        printf("%d: ", it->first);
        it->second();
    }

    for (const auto &[id, func] : m) {
        printf("%d: ", id);
        func();
    }

    int ints[] = {1, 2, 3};
    for (const auto &i : ints) {
        printf("%d\n", i);
    }

    StyledTexts texts;
    texts.PushStyle({.color = 0xff0000ff, .families = "serif"});
    texts.AddText("123");
    texts.PushStyle({.color = 0xffff0000, .families = "sans-serif"});
    texts.AddText("456");
    texts.PopStyle();
    texts.AddText("789");
    for (auto &text : texts) {
        printf("text: %s, color: %08X, families: %s\n",
               text.text->c_str(), text.style->color, text.style->families);
    }
    return 0;
}
